package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.msg.NewsUpOrDownMsg;
import com.heima.model.wemedia.dtos.WmNewsContentDto;
import com.heima.model.wemedia.dtos.WmNewsDownOrUpDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.entity.MaterialTypeEntity;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmChannelService;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Array;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author brianxia
 * @version 1.0
 * @date 2022-10-21 10:19
 */
@Service
@Slf4j
public class WmNewsServicleImpl extends ServiceImpl<WmNewsMapper, WmNews>
        implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Override
    public PageResponseResult findPage(WmNewsPageReqDto dto) {

        if(WmThreadLocalUtil.getUser() == null){
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }

        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery().eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId())
                .orderByDesc(WmNews::getPublishTime);

        //添加动态条件
        if(dto.getStatus() != null){
            wrapper.eq(WmNews::getStatus,dto.getStatus());
        }

        if(StringUtils.isNotBlank(dto.getKeyword())){
            wrapper.like(WmNews::getTitle,dto.getKeyword());
        }

        if(dto.getChannelId() != null){
            wrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }

        if(dto.getBeginPubDate() != null && dto.getEndPubDate() != null){
           // wrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
            wrapper.ge(WmNews::getPublishTime,dto.getBeginPubDate())
                    .lt(WmNews::getPublishTime,dto.getEndPubDate());
        }

        Page<WmNews> page = page(new Page<>(dto.getPage(), dto.getSize()), wrapper);

        PageResponseResult result = new PageResponseResult((int) page.getCurrent(),
                (int) page.getSize(), (int) page.getTotal());
        result.setData(page.getRecords());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(WmNewsDto dto) {

        if(WmThreadLocalUtil.getUser() == null){
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //拿到的是 dto -> 数据库  WmNews
        WmNews wmNews = new WmNews();

        //解析出内容中的图片
        String content = dto.getContent(); //"[{type:text value:'测试数据'},{type:image value:'http://192.168xxxx'}]"
        List<String> contentImageUrls = getContentImageUrls(content);
        //是否是字段选择
        if(Objects.equals(dto.getType(), WemediaConstants.WM_NEWS_TYPE_AUTO)){
            int size = contentImageUrls.size();
            //>=3张取前三张
            if(size >= 3){
                dto.setImages(contentImageUrls.subList(0, 3));
                dto.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
            }else if(size >= 1){
                //1-2张取第一张
                dto.setImages(contentImageUrls.subList(0, 1));
                dto.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
            }else{
                //0张就无图
                dto.setImages(null);
                dto.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }
        }
        BeanUtils.copyProperties(dto,wmNews);

        //images字段不一样需要特殊处理
        if(dto.getImages() != null){
                //["1.jpg","2.jpg"] ->"1.jpg","2.jpg"
            wmNews.setImages(StringUtils.join(dto.getImages(),","));
        }

        //wmNews补充字段
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        //提交待审核 修改提交时间
        if(Objects.equals(dto.getStatus(),WmNews.Status.SUBMIT.getCode())){
            wmNews.setSubmitedTime(new Date());
        }

        if(dto.getId() == null){
            //新增
            wmNews.setCreatedTime(new Date());
            wmNews.setEnable((short)1);

            save(wmNews);
        }else{
            //删除当前这篇文章和所有图片绑定关系
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId,wmNews.getId())
            );
            //修改
            updateById(wmNews);
        }

        if(Objects.equals(dto.getStatus(),WmNews.Status.NORMAL.getCode())){
            //如果是草稿,直接返回，不去创建图片和文章关联关系。草稿中的图片可以随意删除
            return;
        }

        //执行两个sql语句
        List<MaterialTypeEntity> materialTypeEntities = new ArrayList<>();
        //内容中的图片

        getMaterialTypeEntities(materialTypeEntities, contentImageUrls,WemediaConstants.WM_CONTENT_REFERENCE);
        //封面中的图片
        getMaterialTypeEntities(materialTypeEntities, dto.getImages(),WemediaConstants.WM_COVER_REFERENCE);

        if(CollectionUtils.isNotEmpty(materialTypeEntities)){
            wmNewsMaterialMapper.saveBatchRelation2(materialTypeEntities,wmNews.getId());
        }

//        //添加内容中的图片  素材ID 文章ID 类型 0内容 1封面 排序（foreach自动生成）
//        saveImagesAndNewsRelation(contentImageUrls,wmNews.getId(),WemediaConstants.WM_CONTENT_REFERENCE);
//
//        //添加封面中的图片
//        saveImagesAndNewsRelation(dto.getImages(),wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);

        //开启审核 文章立即发布
        wmNewsAutoScanService.autoScan(wmNews);
    }

    @Override
    public void downOrUp(WmNewsDownOrUpDto dto) {
        Long id = dto.getId();
        //1.查询文章
        WmNews wmNews = getById(id);
        if(wmNews == null){
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //2.是否发布
        if(!Objects.equals(wmNews.getStatus(),WmNews.Status.PUBLISHED.getCode())){
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"文章状态不正确");
        }

        //3.判断状态是否一致
        if(Objects.equals(wmNews.getEnable(),dto.getEnable())){
            return;
        }

        boolean update = update(Wrappers.<WmNews>lambdaUpdate().eq(WmNews::getId, dto.getId())
                .eq(WmNews::getUserId, WmThreadLocalUtil.getUser().getId())
                .set(WmNews::getEnable, dto.getEnable()));

        if(!update){
            throw new CustomException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }

        //发消息
        NewsUpOrDownMsg msg = new NewsUpOrDownMsg();
        msg.setArticleId(wmNews.getArticleId());
        msg.setEnable(dto.getEnable());

        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,
                JSON.toJSONString(msg));

    }

    private void getMaterialTypeEntities(List<MaterialTypeEntity> materialTypeEntities,
                                         List<String> urls,
                                         short type) {
        List<Integer> contentIds = getMaterialIdsByUrl(urls);
        if(CollectionUtils.isNotEmpty(contentIds)){
            for (Integer contentId : contentIds) {
                MaterialTypeEntity materialTypeEntity = new MaterialTypeEntity();
                materialTypeEntity.setType(type);
                materialTypeEntity.setId(contentId);
                materialTypeEntities.add(materialTypeEntity);
            }
        }
    }

    private List<Integer> getMaterialIdsByUrl(List<String> imageUrls){
        //没有图片，不需要处理
        if(CollectionUtils.isEmpty(imageUrls)){
            return null;
        }
        //查询url对应的id
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, imageUrls)
                .select(WmMaterial::getId));
        //判断取出来的数据id是否数量一致
        if(wmMaterials.size() != imageUrls.size()){
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"素材图片已经不存在!");
        }

        List<Integer> ids = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());

        return ids;
    }

    private void saveImagesAndNewsRelation(List<String> imageUrls, Integer id, Short type) {

        List<Integer> ids = getMaterialIdsByUrl(imageUrls);
        if(ids == null){
            return;
        }

        wmNewsMaterialMapper.saveBatchRelation(ids,id,type);
    }

    private List<String> getContentImageUrls(String content) {

        List<WmNewsContentDto> wmNewsContentDtos
                = JSON.parseArray(content, WmNewsContentDto.class);
        //做一个去重操作

//        HashSet<String> urls = new HashSet<>();
//        for (WmNewsContentDto wmNewsContentDto : wmNewsContentDtos) {
//            if(Objects.equals(wmNewsContentDto.getType(),WemediaConstants.WM_NEWS_TYPE_IMAGE)){
//                urls.add(wmNewsContentDto.getValue());
//            }
//        }
//        return new ArrayList<String>(urls);

        //用stream流处理
        List<String> collect = wmNewsContentDtos.stream().filter(x -> Objects.equals(x.getType(), WemediaConstants.WM_NEWS_TYPE_IMAGE))
                .map(WmNewsContentDto::getValue).distinct().collect(Collectors.toList());
        return collect;
    }

    public static void main(String[] args) {

        ArrayList<String> strings = new ArrayList<>();
        strings.add("1");
        strings.add("2");
        System.out.println(StringUtils.join(strings,","));
    }
}
